﻿using RRQMSocket;
using RRQMSocketServer.server;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace RRQMSocketServer
{
    public partial class SocketBaseFramwork : Form
    {

        public static SocketBaseFramwork Instance;

        //Tcp服务
        private VIPTcpService vipTcpService;

        //是否开启了服务器
        private bool isStartServer;

        public SocketBaseFramwork()
        {
            InitializeComponent();
            CheckForIllegalCrossThreadCalls = false;
            Instance = this;
            this.listView1.Columns.Add("时间", 120, HorizontalAlignment.Left);
            this.listView1.Columns.Add("日志", 120, HorizontalAlignment.Left);
            this.listView1.BeginUpdate();
            //listView1.Items.Add("呵呵1");
            //listView1.Items.Add("呵呵2");
            //listView1.Items.Add("呵呵3");
        }

        private void BtnStartServer_Click(object sender, EventArgs e)
        {
            if (TxBoxIPHost.Text == "" || TxBoxIPHost.Text == null) {
                AddLog("IP地址:端口不能为空");
                return;
            }
            bool isIPHost = CheckIPHost(TxBoxIPHost.Text);
            if (!isIPHost) {
                AddLog("IPHost格式不正确");
                return;
            }
            if (!isStartServer)
            {
                isStartServer = true;
            }
            else
            {
                return;
            }
            vipTcpService = new VIPTcpService();
            vipTcpService.ClientConnected += ClientConnected;
            vipTcpService.ClientDisconnected += ClientDisconnected;
            IPHost ipHost = new IPHost(TxBoxIPHost.Text);

            //声明配置
            var config = new TcpServiceConfig();
            config.ListenIPHosts = new IPHost[] { ipHost };//同时监听两个地址
            config.BufferLength = 1024 * 64;//缓存池容量
            config.BytePoolMaxSize = 512 * 1024 * 1024;//单个线程内存池容量
            config.BytePoolMaxBlockSize = 20 * 1024 * 1024;//单个线程内存块限制
            config.Logger = new Log();//日志记录器，可以自行实现ILog接口。
            config.ServerName = "RRQMService";//服务名称
            config.SeparateThreadReceive = false;//独立线程接收，当为true时可能会发生内存池暴涨的情况
            config.ThreadCount = 5;//多线程数量，当SeparateThreadReceive为false时，该值只决定BytePool的数量。
            config.Backlog = 30;
            config.ClearInterval = 60 * 1000;//60秒无数据交互会清理客户端
            config.ClearType = ClearType.Receive | ClearType.Send;//清理统计
            config.MaxCount = 10000;//最大连接数

            //载入配置
            vipTcpService.Setup(config);


            try
            {
                //启动服务器
                vipTcpService.Start();
                LbServerState.Text = "true";
                AddLog("服务器已开启");
            }
            catch (Exception ex) {
                AddLog("服务器启动失败："+ex.Message);
            }
        }

        private void ClientConnected(object sender, MesEventArgs e)
        {
            AddClientNum();
            string ip = ((VIPTcpSocketClient)sender).IP;
            AddLog("[" + ip + "]已连接");
        }

        private void ClientDisconnected(object sender, MesEventArgs e)
        {
            ReduceClientNum();
            string ip = ((VIPTcpSocketClient)sender).IP;
            AddLog("[" + ip + "]断开连接");
        }

        private void BtnStopServer_Click(object sender, EventArgs e)
        {
            if (isStartServer)
            {
                isStartServer = false;
                vipTcpService.Dispose();
                LbServerState.Text = "false";
                AddLog("服务器已停止");
            }
        }

        private void SocketBaseFramwork_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (!isStartServer) {
                return;
            }
            DialogResult dr = MessageBox.Show("服务器正在运行，确认关闭?", "提示:", MessageBoxButtons.OKCancel, MessageBoxIcon.Information);
            //如果单击“是”按钮
            if (dr == DialogResult.OK)
            {
                //关闭窗体
                e.Cancel = false;
                if (vipTcpService != null && isStartServer)
                {
                    //关闭服务器并释放资源
                    vipTcpService.Dispose();
                }
            }
            else if (dr == DialogResult.Cancel)
            {
                //不执行操作
                e.Cancel = true;
            }
        }

        /// 正规则试验IPHost
        /// </summary>
        /// <param name="ipHost"></param>
        /// <returns></returns>
        public bool CheckIPHost(string ipHost)
        {
            string[] strArr = ipHost.Split(':');
            if (strArr.Length != 2)
            {
                return false;
            }
            string ip = strArr[0];
            ip = ip.Trim();
            //模式字符串
            string pattern = @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$";
            //验证
            bool isIp = Regex.IsMatch(ip, pattern);
            string port = strArr[1];
            int portNum;
            bool isPort = int.TryParse(port, out portNum);
            if (isPort && portNum >= 0 && portNum <= 65535)
            {
                isPort = true;
            }
            else
            {
                isPort = false;
            }
            return isIp && isPort;
        }

        public void AddClientNum()
        {
            string clientNumStr = LbClientNum.Text;
            int clientNum;
            bool isClientNum = int.TryParse(clientNumStr, out clientNum);
            if (isClientNum)
            {
                clientNum++;
            }
            ShowClientNum(clientNum.ToString());
        }

        public void ReduceClientNum()
        {
            string clientNumStr = LbClientNum.Text;
            int clientNum;
            bool isClientNum = int.TryParse(clientNumStr, out clientNum);
            if (isClientNum)
            {
                clientNum--;
            }
            ShowClientNum(clientNum.ToString());
        }

        public void ShowClientNum(string clientNum)
        {
            this.Invoke(new Action(() => {
                LbClientNum.Text = clientNum;
            }));
        }

        public void AddLog(string log) {
            this.Invoke(new Action(() => {
                string msg = DateTime.Now.ToString("F") + " " + log;
                LsBoxLogList.Items.Insert(0, msg);
            }));
        }

    }
}
